#!/usr/bin/python
# -*- coding: utf-8 -*-
'''
Created on 25/dic/2009

@author: fabio
'''
import Spy
import commands
import getopt
import sys
import wx

myALARM_EVENT = wx.NewEventType()
ALARM_EVENT = wx.PyEventBinder(myALARM_EVENT, 1)

class Observer(wx.App):

    def OnInit(self):
        frame = MainFrame(None, -1, "Observer")
        frame.Show(True)
        self.SetTopWindow(frame)
        
        return True
    
class HiddenObserver(wx.App):
    
    def OnInit(self):
        MainFrame(None, -1, "Observer")
        
        return True

class MainFrame(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition,
                          wx.Size(480,400))
        self.Centre()
        self.Bind(wx.EVT_CLOSE, self.OnClose)
        content = wx.Panel(self, -1)
        
        #taskbar
        self.__tbicon = MyTaskBarIcon(self)
        
        #barra di stato
        self.CreateStatusBar()
        self.SetStatusText("Benvenuto in Observer")
        
        #toolbar
        tb = self.CreateToolBar(wx.TB_HORIZONTAL|wx.NO_BORDER|wx.TB_FLAT)
        self.__toolbar = tb
        
        ##Url
        tc = wx.TextCtrl(tb, -1, "http://", size=(200,25))
        tb.AddControl(tc)
        self.__url = tc
        
        ##delay
        sb = wx.SpinCtrl(tb, -1, '10', size=(50,25), min=5, max=120)
        tb.AddControl(sb)
        self.__delay = sb
        
        tb.AddControl(wx.StaticText(tb, -1, "min"))
        
        ##aggiungi
        ADD_BUTTON = wx.NewId()
        bmpadd = wx.Bitmap('images/add_url.png', wx.BITMAP_TYPE_PNG)
        tb.AddSimpleTool(ADD_BUTTON, bmpadd, 'Aggiungi', "Aggiungi un nuovo url")
        wx.EVT_TOOL(self, ADD_BUTTON, self.OnAdd)
        self.__ADD_BUTTON = ADD_BUTTON
        self.__bmpadd = bmpadd
        
        ##modifica (invisibile)
        EDIT_BUTTON = wx.NewId()
        bmpedit = wx.Bitmap('images/edit_url.png', wx.BITMAP_TYPE_PNG)
        wx.EVT_TOOL(self, EDIT_BUTTON, self.OnEdit)
        self.__EDIT_BUTTON = EDIT_BUTTON
        self.__bmpedit = bmpedit

        ##elimina
        DELETE_BUTTON = wx.NewId()
        bmp = wx.Bitmap('images/delete_url.png', wx.BITMAP_TYPE_PNG)
        tb.AddSimpleTool(DELETE_BUTTON, bmp, 'Elimina', "Elimina l'url selezionato")
        tb.EnableTool(DELETE_BUTTON, False)
        wx.EVT_TOOL(self, DELETE_BUTTON, self.OnDelete)
        self.__DELETE_BUTTON = DELETE_BUTTON
        
        self.__mode = "add"
        
        ##separatore
        tb.AddSeparator()
        
        ##start
        START_BUTTON = wx.NewId()
        bmpstart = wx.Bitmap('images/start.png', wx.BITMAP_TYPE_PNG)
        tb.AddSimpleTool(START_BUTTON, bmpstart, 'Avvia', "Avvia il monitoraggio")
        wx.EVT_TOOL(self, START_BUTTON, self.OnStartStop)
        self.__START_BUTTON = START_BUTTON
        self.__bmpstart = bmpstart
        
        ##stop
        STOP_BUTTON = wx.NewId()
        bmpstop = wx.Bitmap('images/stop.png', wx.BITMAP_TYPE_PNG)
        #tb.AddSimpleTool(STOP_BUTTON, bmpstop, 'Avvia', "Avvia il monitoraggio")
        wx.EVT_TOOL(self, STOP_BUTTON, self.OnStartStop)
        self.__STOP_BUTTON = STOP_BUTTON
        self.__bmpstop = bmpstop
        
        self.__run = False
        
        ##separatore
        tb.AddSeparator()
        
        ##Nascondi
        HIDDEN_BUTTON = wx.NewId()
        bmp = wx.Bitmap('images/hide.png', wx.BITMAP_TYPE_PNG)
        tb.AddSimpleTool(HIDDEN_BUTTON, bmp, 'Nascondi', "Il" +
                         " programma e' raggiungibile dalla system try")
        wx.EVT_TOOL(self, HIDDEN_BUTTON, self.OnHidden)
        
        tb.Realize()
        
        #Crea contenuto spazio utente (lista report)
        sizer = wx.BoxSizer(wx.VERTICAL)
        
        LIST_REPORT = wx.NewId()
        lc = wx.ListCtrl(self, LIST_REPORT,
                         style=wx.LC_REPORT|wx.NO_BORDER|wx.LC_HRULES)
        lc.InsertColumn(0, 'Url')
        lc.InsertColumn(1, 'Ritardo')
        lc.InsertColumn(2, 'Riferimento')
        lc.SetColumnWidth(0, 200)
        lc.SetColumnWidth(1, 80)
        lc.SetColumnWidth(2, 200)
#        lc.getAlignment(lc.l) setto l'allineamento al centro
        wx.EVT_LIST_ITEM_SELECTED(self, LIST_REPORT, self.OnSelect)
        lc.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.OnDeselect)
        
        self.__report = lc
        
        sizer.Add(lc, 1, wx.EXPAND, 0)
        self.SetSizer(sizer)
        sizer.Fit(content)
        self.Layout()
        ####
        
        self.__spies = self.fromFile()
        self.fillList()

        #for spy in self.__spies:
        #    spy.start()
        
        self.Bind(ALARM_EVENT, self.prova, id=self.GetId())
        self.__dialog = wx.MessageDialog(self, "ciao", 'Attenzione',
                                         wx.OK|wx.ICON_INFORMATION)
        
    def prova(self, event):
        print "ciao"
        self.__dialog.ShowModal()
            
    def OnInfo(self, event):
        #dlg = wx.Dialog(self, -1, "Informazioni", wx.Point(50,50),
        #                wx.Size(200, 200))
        #st = wx.TextCtrl(dlg, -1, "Informazioni", wx.Point(10,10))
        #st.SetValue("Il programma mostra una finestra con alcuni menu")
        #dlg.ShowModal()
        #dlg.Destroy()
        pass
        
    def OnClose(self, event):
        for spy in self.__spies:
            spy.terminate()
        self.__tbicon.Destroy()
        self.toFile()
        self.Destroy()
        
    def OnHidden(self, event):
        self.Hide()
        
    def OnAdd(self, event):
        url = self.__url.GetValue()
        delay = self.__delay.GetValue()
        
        if url != "http://":
            spy = Spy.Spy(self, {"url" : url, "delay" : delay})
            self.__spies.append(spy)
            self.addList(spy)
            #for spy in self.__spies:###
            #    print repr(spy)
    
    def OnEdit(self, event):
        selected = self.__report.GetFirstSelected()

        url = self.__url.GetValue()
        delay = str(self.__delay.GetValue())
        self.__report.SetStringItem(selected, 0, url)
        self.__report.SetStringItem(selected, 1, delay)
        self.__spies[selected].url = url
        self.__spies[selected].delay = delay
        
        self.DefaultValue()
        self.EditToAddIcon()
            
    def OnSelect(self, event):
        if self.__mode == "add":
            self.__toolbar.DeleteTool(self.__ADD_BUTTON)
            self.__toolbar.InsertSimpleTool(3, self.__EDIT_BUTTON, self.__bmpedit, 'Modifica', "Modifica l'url selezionato")
            self.__toolbar.EnableTool(self.__DELETE_BUTTON, True)
            self.__mode = "edit"
            
        selected = event.GetIndex()    
        self.__url.SetValue(self.__report.GetItem(selected, 0).GetText())
        self.__delay.SetValue(int(self.__report.GetItem(selected, 1).GetText()))
        
    def OnDeselect(self, event):
        self.EditToAddIcon()
        self.DefaultValue()
        
    def DefaultValue(self):
        self.__url.SetValue("http://")
        self.__delay.SetValue(10)
                
    def EditToAddIcon(self):
        if self.__mode == "edit":
            self.__toolbar.DeleteTool(self.__EDIT_BUTTON)
            self.__toolbar.InsertSimpleTool(3, self.__ADD_BUTTON, self.__bmpadd, 'Aggiungi', "Aggiungi un nuovo url")
            self.__toolbar.EnableTool(self.__DELETE_BUTTON, False)
            self.__mode = "add"
        
    def OnDelete(self, event):
        selected = self.__report.GetFirstSelected()
        if selected != -1:
            self.__report.DeleteItem(selected)       
            
            self.__spies[selected].live = False
            del self.__spies[selected]
            
            #for spy in self.__spies:###
            #    print repr(spy)
                
            self.EditToAddIcon()
            self.DefaultValue()
            
    def OnStartStop(self, event):
        if not self.__run:
            try:
                for spy in self.__spies:
                    spy.start()
            except RuntimeError:
                for spy in self.__spies:
                    spy.resume()
                
            self.__toolbar.DeleteTool(self.__START_BUTTON)
            self.__toolbar.InsertSimpleTool(6, self.__STOP_BUTTON, self.__bmpstop, 'Ferma', "Ferma il monitoraggio")            
            self.__run = True            
        else:
            
            for spy in self.__spies:
                spy.pause()
            
            self.__toolbar.DeleteTool(self.__STOP_BUTTON)
            self.__toolbar.InsertSimpleTool(6, self.__START_BUTTON, self.__bmpstart, 'Avvia', "Avvia il monitoraggio")            
            self.__run = False           
        
    def alarm(self, url, date):
        print "Ho riscontrato un cambiamento della risorsa web: '%s' " % url + \
              "in riferimento alla stessa nel giorno e l'ora: %s" % date
                      
        evt = AlarmEvent(myALARM_EVENT, self.GetId())
        #evt.setMyVal(val)
        self.GetEventHandler().ProcessEvent(evt)
              
        return
        #creare un evento che apre la finestra
    
        message = """Il file che stai osservando e' stato modificato!
                     Verra' aperto il seguente URL: %s""" % url

        self.pop_message(message)
        
        if(wx.GetOsDescription().startswith("Mac")):
            commands.getoutput("open /Applications/Safari.app " + url)
        elif(wx.GetOsDescription().startswith("Windows")):
            self.pop_message("Passa ad un sistema operativo serio!!")
        else:
            commands.getoutput("firefox " + url)
    
    def pop_message(self, message): 
        dialog = wx.MessageDialog(self, message, 'Attenzione',
                                  wx.OK|wx.ICON_INFORMATION)
        dialog.ShowModal()
        
        dialog.Destroy()
        
    def addList(self, spy):
        self.__report.Append((spy.url, spy.delay))
    
    def fillList(self):
        for spy in self.__spies:
            if spy.hash:
                self.__report.Append((spy.url, spy.delay, spy.date))
            else:
                self.__report.Append((spy.url, spy.delay))
                
            
    def updateItemList(self, spy , date):
        index = self.__spies.index(spy)
        self.__report.SetStringItem(index, 2, str(date))
    
    def toFile(self):
        try:
            f = open('save.dat', 'w')
            for spy in self.__spies:
                f.write("%s\n" % str(spy))
            f.close()
        except IOError:
            print("errore di I/O")
        
    def fromFile(self):
        spies = []
        try:
            f = open('save.dat','r')
            for line in f:
                line = line[:-1]
                fields = line.split(',')
                conf = {"url" : fields[0], "delay" : fields[1]}
                if len(fields) == 4:
                    conf["hash"] = fields[2]
                    conf["date"] = fields[3]
                spies.append(Spy.Spy(self, conf))
        except IOError:
            print("errore di I/O")
            sys.exit(1)
        
        return spies

    
class AlarmEvent(wx.PyEvent):
    def __init__(self, event_type, id):
        wx.PyEvent.__init__(self, id, event_type)
        self.myVal = "didn't fire properly."
 
    def setMyVal(self, val):
        self.myVal = val
     
    def getMyText(self):
        return self.myVal 


class MyTaskBarIcon(wx.TaskBarIcon):
    def __init__(self, frame):
        wx.TaskBarIcon.__init__(self)
        
        self.frame = frame
        self.SetIcon(wx.Icon('images/tray_app_icon.png', wx.BITMAP_TYPE_PNG), 'Observer')
        self.Bind(wx.EVT_MENU, self.OnActivateDeactivate, id=1)
        self.Bind(wx.EVT_MENU, self.OnClose, id=2)
        self.Bind(wx.EVT_TASKBAR_LEFT_DCLICK, self.OnActivateDeactivate)
    
    def CreatePopupMenu(self):
        menu = wx.Menu()
        menu.Append(1, 'Mostra/Nascondi')
        menu.Append(2, 'Chiudi')
        return menu
    
    def OnClose(self, event):
        self.frame.Close()
        self.Destroy()
    
    def OnActivateDeactivate(self, event):        
        if self.frame.IsShown():
            self.frame.Hide()
        else:
            self.frame.Show() 

def initializeArgs(sysargs):
    if not len(sys.argv) in (1, 2):
        usage()
        sys.exit(0)
        
    try:
        optlist, list = getopt.getopt(sysargs, 'h', 'hidden')
    except getopt.GetoptError:
        usage()
        sys.exit(0);
            
    for opt, a in optlist:
        
        if opt == "-h":
            usage()
            sys.exit(0)
            
        if opt == "--hidden":
            print "Sto eseguendo Observer ad avvio nascosto"
            return "hidden"
            
    return "normal"
    
def usage():
    print("usage: " + sys.argv[0] + " --hidden if you want to execute hidden")


if __name__ == "__main__":
    mode = initializeArgs(sys.argv[1:])
    
    if mode == "normal":
        app = Observer(0)
    elif mode == "hidden":
        app = HiddenObserver(0)
    else:
        sys.exit(1)
        
    app.MainLoop()

# si potrebbe aggiungere anche il parametro -s per eseguire il programma avviato
